package com.ms.controller;

import com.ms.annotation.AdminOrOrganizerOnly;
import com.ms.entity.Notice;
import com.ms.entity.NoticeGiven;
import com.ms.entity.Manager;
import com.ms.entity.Organizer;
import com.ms.entity.User;
import com.ms.service.inter.*;
import com.ms.utils.ManagerContext;
import com.ms.utils.SimpleTokenUtils;
import com.ms.utils.UserContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 通知控制器 - 处理通知相关的HTTP请求
 * 包括通知发布、查询、修改等功能
 */
@RestController
@RequestMapping("/notice")
public class NoticeController {

    @Autowired
    private NoticeService noticeService;
    
    @Autowired
    private NoticeGivenService noticeGivenService;
    
    @Autowired
    private ManagerService managerService;
    
    @Autowired
    private OrganizerService organizerService;
    
    @Autowired
    private UserService userService;
    
    // 创建一个线程池用于异步发送通知
    private final ExecutorService executorService = Executors.newFixedThreadPool(10);

    /**
     * 发布通知接口
     * @param notice 通知对象，包含通知信息
     * @param request HTTP请求
     * @return 发布结果
     */
    @PostMapping("/publish")
    @AdminOrOrganizerOnly
    public ResponseEntity<Map<String, Object>> publishNotice(@RequestBody Notice notice, HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 验证token
            String token = request.getHeader("token");
            if (token == null || token.isEmpty()) {
                result.put("success", false);
                result.put("message", "未登录");
                return ResponseEntity.badRequest().body(result);
            }

            // 从token中获取用户信息
            Object managerObj = SimpleTokenUtils.getUserByToken(token);
            Object organizerObj = SimpleTokenUtils.getUserByToken(token);
            
            if ((managerObj == null && organizerObj == null) || 
                (!(managerObj instanceof com.ms.entity.Manager) && 
                 !(organizerObj instanceof com.ms.entity.Organizer))) {
                result.put("success", false);
                result.put("message", "无权限发布通知");
                return ResponseEntity.badRequest().body(result);
            }

            // 设置发送者类型和ID
            // 设置审核状态 - 管理员发布自动通过，主办方发布需要审核
            if (managerObj instanceof com.ms.entity.Manager) {
                notice.setSenderType(0); // 管理员
                notice.setSenderId(((com.ms.entity.Manager) managerObj).getMaId());
                notice.setIsUsing(true); // 管理员发布自动通过审核
            } else if (organizerObj instanceof com.ms.entity.Organizer) {
                notice.setSenderType(1); // 主办方
                notice.setSenderId(((com.ms.entity.Organizer) organizerObj).getOrId());
                notice.setIsUsing(false); // 主办方发布需要审核
            }

            // 设置创建时间
            notice.setCreateTime(new Date());

            // 保存通知
            noticeService.save(notice);

            // 如果是管理员发布的通知，立即发送给接收者
            if (managerObj instanceof com.ms.entity.Manager) {
                // 异步发送通知
                CompletableFuture.runAsync(() -> {
                    try {
                        sendNoticeToReceivers(notice);
                    } catch (Exception e) {
                        e.printStackTrace(); // 打印异常信息
                    }
                }, executorService);
            }

            if (managerObj instanceof com.ms.entity.Manager) {
                result.put("success", true);
                result.put("message", "通知发布成功");
            } else {
                result.put("success", true);
                result.put("message", "通知发布成功，等待审核");
            }
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "发布通知失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 获取当前用户发布的所有通知接口
     * @param request HTTP请求
     * @return 通知列表
     */
    @GetMapping("/my")
    @AdminOrOrganizerOnly
    public ResponseEntity<Map<String, Object>> getMyNotices(HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 验证token
            String token = request.getHeader("token");
            if (token == null || token.isEmpty()) {
                result.put("success", false);
                result.put("message", "未登录");
                return ResponseEntity.badRequest().body(result);
            }

            // 从token中获取用户信息
            Object managerObj = SimpleTokenUtils.getUserByToken(token);
            Object organizerObj = SimpleTokenUtils.getUserByToken(token);

            if ((managerObj == null && organizerObj == null) || 
                (!(managerObj instanceof com.ms.entity.Manager) && 
                 !(organizerObj instanceof com.ms.entity.Organizer))) {
                result.put("success", false);
                result.put("message", "无权限获取通知");
                return ResponseEntity.badRequest().body(result);
            }

            // 根据发送者类型和ID获取通知
            List<Notice> notices;
            if (managerObj instanceof com.ms.entity.Manager) {
                // 管理员
                com.ms.entity.Manager manager = (com.ms.entity.Manager) managerObj;
                notices = noticeService.findBySenderTypeAndSenderId(0, manager.getMaId());
            } else {
                // 主办方
                com.ms.entity.Organizer organizer = (com.ms.entity.Organizer) organizerObj;
                notices = noticeService.findBySenderTypeAndSenderId(1, organizer.getOrId());
            }

            result.put("success", true);
            result.put("notices", notices);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取通知列表失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 审核通知接口
     * @param id 通知ID
     * @param isUsing 是否通过审核
     * @param request HTTP请求
     * @return 审核结果
     */
    @PutMapping("/review")
    public ResponseEntity<Map<String, Object>> reviewNotice(@RequestParam Integer id, 
                                                           @RequestParam Boolean isUsing,
                                                           HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 验证token
            String token = request.getHeader("token");
            if (token == null || token.isEmpty()) {
                result.put("success", false);
                result.put("message", "未登录");
                return ResponseEntity.badRequest().body(result);
            }

            // 从token中获取管理员信息
            Object managerObj = SimpleTokenUtils.getUserByToken(token);
            if (!(managerObj instanceof com.ms.entity.Manager)) {
                result.put("success", false);
                result.put("message", "无权限审核通知");
                return ResponseEntity.badRequest().body(result);
            }

            Notice notice = noticeService.findById(id);
            if (notice == null) {
                result.put("success", false);
                result.put("message", "通知不存在");
                return ResponseEntity.badRequest().body(result);
            }

            // 更新审核状态
            notice.setIsUsing(isUsing);
            noticeService.update(notice);

            // 如果审核通过，则异步发送通知给相应的接收者
            if (isUsing) {
                CompletableFuture.runAsync(() -> {
                    try {
                        sendNoticeToReceivers(notice);
                    } catch (Exception e) {
                        e.printStackTrace(); // 打印异常信息
                    }
                }, executorService);
            }
            
            // 如果是主办方发布的通知，通知主办方审核结果
            if (notice.getSenderType() == 1) { // 主办方发布的通知
                CompletableFuture.runAsync(() -> {
                    try {
                        notifyOrganizerAboutReviewResult(notice, isUsing);
                    } catch (Exception e) {
                        e.printStackTrace(); // 打印异常信息
                    }
                }, executorService);
            }

            result.put("success", true);
            result.put("message", "审核状态更新成功");
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "审核通知失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }


    // ////////////////////////////////////////////////////////////////////////////
    // ////////////////////////////////////////////////////////////////////////////
    // ////////////////////////////////////////////////////////////////////////////
    /**
     * 获取所有已审核通知接口
     * @return 通知列表
     */
    @GetMapping("/list")
    public ResponseEntity<Map<String, Object>> getAllNotices() {
        Map<String, Object> result = new HashMap<>();

        try {
            List<Notice> notices = noticeService.findByIsUsing(true);
            
            result.put("success", true);
            result.put("notices", notices);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取通知列表失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 根据ID获取通知详情接口
     * @param id 通知ID
     * @return 通知详情
     */
    @GetMapping("/detail")
    public ResponseEntity<Map<String, Object>> getNoticeDetail(@RequestParam Integer id) {
        Map<String, Object> result = new HashMap<>();

        try {
            Notice notice = noticeService.findById(id);
            
            if (notice == null) {
                result.put("success", false);
                result.put("message", "通知不存在");
                return ResponseEntity.badRequest().body(result);
            }
            
            // 只有已审核的通知才能查看
            if (!notice.getIsUsing()) {
                result.put("success", false);
                result.put("message", "该通知尚未审核通过");
                return ResponseEntity.badRequest().body(result);
            }

            result.put("success", true);
            result.put("notice", notice);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取通知详情失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 根据接收者类型获取通知接口
     * @param receiverType 接收者类型
     * @return 通知列表
     */
    @GetMapping("/byReceiverType")
    public ResponseEntity<Map<String, Object>> getNoticesByReceiverType(@RequestParam Integer receiverType) {
        Map<String, Object> result = new HashMap<>();

        try {
            List<Notice> notices = noticeService.findByReceiverType(receiverType);
            
            // 过滤出已审核的通知
            List<Notice> filteredNotices = notices.stream()
                    .filter(Notice::getIsUsing)
                    .toList();
            
            result.put("success", true);
            result.put("notices", filteredNotices);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取通知列表失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 删除通知接口
     * @param id 通知ID
     * @param request HTTP请求
     * @return 删除结果
     */
    @DeleteMapping("/delete")
    public ResponseEntity<Map<String, Object>> deleteNotice(@RequestParam Integer id, HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 验证token
            String token = request.getHeader("token");
            if (token == null || token.isEmpty()) {
                result.put("success", false);
                result.put("message", "未登录");
                return ResponseEntity.badRequest().body(result);
            }

            // 从token中获取管理员信息
            Object managerObj = SimpleTokenUtils.getUserByToken(token);
            if (!(managerObj instanceof com.ms.entity.Manager)) {
                result.put("success", false);
                result.put("message", "无权限删除通知");
                return ResponseEntity.badRequest().body(result);
            }

            Notice notice = noticeService.findById(id);
            if (notice == null) {
                result.put("success", false);
                result.put("message", "通知不存在");
                return ResponseEntity.badRequest().body(result);
            }

            noticeService.delete(id);

            result.put("success", true);
            result.put("message", "删除成功");
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "删除通知失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 获取待审核通知接口（只有管理员可以访问）
     * @param request HTTP请求
     * @return 待审核通知列表
     */
    @GetMapping("/pending")
    public ResponseEntity<Map<String, Object>> getPendingNotices(HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 验证token
            String token = request.getHeader("token");
            if (token == null || token.isEmpty()) {
                result.put("success", false);
                result.put("message", "未登录");
                return ResponseEntity.badRequest().body(result);
            }

            // 从token中获取管理员信息
            Object managerObj = SimpleTokenUtils.getUserByToken(token);
            if (!(managerObj instanceof com.ms.entity.Manager)) {
                result.put("success", false);
                result.put("message", "无权限访问");
                return ResponseEntity.badRequest().body(result);
            }

            // 获取所有待审核的通知（isUsing = false）
            List<Notice> pendingNotices = noticeService.findByIsUsing(false);

            result.put("success", true);
            result.put("notices", pendingNotices);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取待审核通知失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
    
    /**
     * 发送通知给接收者
     * @param notice 通知对象
     */
    private void sendNoticeToReceivers(Notice notice) {
        Integer receiverType = notice.getReceiverType();
        Date now = new Date();
        
        switch (receiverType) {
            case 1: // 所有人
                sendToAll(now, notice.getId());
                break;
            case 2: // 管理员
                sendToManagers(now, notice.getId());
                break;
            case 3: // 主办方
                sendToOrganizers(now, notice.getId());
                break;
            case 4: // 用户
                sendToUsers(now, notice.getId());
                break;
            case 5: // 非管理员
                sendToNonManagers(now, notice.getId());
                break;
            case 6: // 非主办方
                sendToNonOrganizers(now, notice.getId());
                break;
            case 7: // 非用户
                sendToNonUsers(now, notice.getId());
                break;
            default:
                // 单独发送或其他情况不处理
                break;
        }
    }
    
    /**
     * 发送通知给所有人
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToAll(Date sendTime, Integer noticeId) {
        // 发送给所有管理员
        sendToManagers(sendTime, noticeId);
        
        // 发送给所有主办方
        sendToOrganizers(sendTime, noticeId);
        
        // 发送给所有用户
        sendToUsers(sendTime, noticeId);
    }
    
    /**
     * 发送通知给所有管理员
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToManagers(Date sendTime, Integer noticeId) {
        List<Manager> managers = managerService.findAll();
        for (Manager manager : managers) {
            NoticeGiven noticeGiven = new NoticeGiven();
            noticeGiven.setNId(noticeId);
            noticeGiven.setMId(manager.getMaId());
            noticeGiven.setSendTime(sendTime);
            noticeGiven.setIsRead(0); // 未读
            noticeGivenService.save(noticeGiven);
        }
    }
    
    /**
     * 发送通知给所有主办方
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToOrganizers(Date sendTime, Integer noticeId) {
        List<Organizer> organizers = organizerService.findAll();
        for (Organizer organizer : organizers) {
            NoticeGiven noticeGiven = new NoticeGiven();
            noticeGiven.setNId(noticeId);
            noticeGiven.setOId(organizer.getOrId());
            noticeGiven.setSendTime(sendTime);
            noticeGiven.setIsRead(0); // 未读
            noticeGivenService.save(noticeGiven);
        }
    }
    
    /**
     * 发送通知给所有用户
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToUsers(Date sendTime, Integer noticeId) {
        List<User> users = userService.findAll();
        for (User user : users) {
            NoticeGiven noticeGiven = new NoticeGiven();
            noticeGiven.setNId(noticeId);
            noticeGiven.setUId(user.getUserID());
            noticeGiven.setSendTime(sendTime);
            noticeGiven.setIsRead(0); // 未读
            noticeGivenService.save(noticeGiven);
        }
    }
    
    /**
     * 发送通知给非管理员（主办方和用户）
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToNonManagers(Date sendTime, Integer noticeId) {
        // 发送给所有主办方
        sendToOrganizers(sendTime, noticeId);
        
        // 发送给所有用户
        sendToUsers(sendTime, noticeId);
    }
    
    /**
     * 发送通知给非主办方（管理员和用户）
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToNonOrganizers(Date sendTime, Integer noticeId) {
        // 发送给所有管理员
        sendToManagers(sendTime, noticeId);
        
        // 发送给所有用户
        sendToUsers(sendTime, noticeId);
    }
    
    /**
     * 发送通知给非用户（管理员和主办方）
     * @param sendTime 发送时间
     * @param noticeId 通知ID
     */
    private void sendToNonUsers(Date sendTime, Integer noticeId) {
        // 发送给所有管理员
        sendToManagers(sendTime, noticeId);
        
        // 发送给所有主办方
        sendToOrganizers(sendTime, noticeId);
    }
    
    /**
     * 通知主办方其发布的通知审核结果
     * @param notice 通知对象
     * @param isApproved 是否通过审核
     */
    private void notifyOrganizerAboutReviewResult(Notice notice, boolean isApproved) {
        try {
            // 创建一条专门给主办方的通知，告知审核结果
            Notice reviewResultNotice = new Notice();
            reviewResultNotice.setSenderType(0); // 管理员发送
            reviewResultNotice.setSenderId(1); // 默认管理员ID
            reviewResultNotice.setReceiverType(3); // 发送给主办方
            reviewResultNotice.setReceiverId(notice.getSenderId()); // 发送给原通知的发布者
            reviewResultNotice.setTitle("通知审核结果");
            reviewResultNotice.setContent(String.format("您发布的标题为\"%s\"的通知已%s。", 
                notice.getTitle(), isApproved ? "通过审核" : "未通过审核"));
            reviewResultNotice.setCreateTime(new Date());
            reviewResultNotice.setIsUsing(true); // 自动通过
            
            // 保存通知
            noticeService.save(reviewResultNotice);
            
            // 发送给对应的主办方
            NoticeGiven noticeGiven = new NoticeGiven();
            noticeGiven.setNId(reviewResultNotice.getId());
            noticeGiven.setOId(notice.getSenderId());
            noticeGiven.setSendTime(new Date());
            noticeGiven.setIsRead(0); // 未读
            noticeGivenService.save(noticeGiven);
        } catch (Exception e) {
            // 记录错误但不中断主流程
            e.printStackTrace();
        }
    }
}
